package cn.yshujia.repository;

import cn.yshujia.domain.entity.Classify;
import cn.yshujia.domain.entity.Label;
import cn.yshujia.domain.vo.LabelVO;
import cn.yshujia.mapper.LabelMapper;
import cn.yshujia.service.impl.ClassifyServiceImpl;
import cn.yshujia.transform.LabelTransform;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Repository;
import org.springframework.util.ObjectUtils;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author YShuJia
 * @create 2024/11/29
 * @description LabelRepository
 */

@Repository
public class LabelRepository {
	
	@Resource
	RedisTemplate<String, LabelVO> redis;
	
	@Resource
	public LabelMapper mapper;
	
	@Resource
	public ClassifyServiceImpl classifyService;
	
	public static final String VO = "label:";
	
	public static final String LIST = "label:list:";
	
	public static final String LIST_TYPE = "label:list:type:";
	
	public static final Duration DURATION = Duration.ofDays(3L);
	
	public List<LabelVO> selectListByClassifyId(Long classifyId) {
		List<LabelVO> voList = redis.opsForList().range(LIST + classifyId, 0L, -1L);
		if (!ObjectUtils.isEmpty(voList)) {
			return voList;
		}
		voList = new ArrayList<>();
		List<Label> list = mapper.selectList(new LambdaQueryWrapper<Label>()
				.eq(Label::getClassifyId, classifyId)
				.orderByDesc(Label::getId));
		if (ObjectUtils.isEmpty(list)) {
			return voList;
		}
		for (Label label : list) {
			voList.add(createLabelVO(label));
		}
		set(voList, LIST + classifyId);
		return voList;
	}
	
	public List<LabelVO> selectListByClassifyType(Integer type) {
		List<LabelVO> voList = redis.opsForList().range(LIST_TYPE + type, 0L, -1L);
		if (!ObjectUtils.isEmpty(voList)) {
			return voList;
		}
		
		List<Long> ids = classifyService.getIdsByType(type);
		voList = new ArrayList<>();
		List<Label> list = mapper.selectList(new LambdaQueryWrapper<Label>().in(Label::getClassifyId, ids));
		if (ObjectUtils.isEmpty(list)) {
			return voList;
		}
		for (Label label : list) {
			voList.add(createLabelVO(label));
		}
		set(voList, LIST_TYPE + type);
		return voList;
	}
	
	
	public LabelVO get(Long id) {
		LabelVO labelVO = redis.opsForValue().get(VO + id);
		if (!ObjectUtils.isEmpty(labelVO)) {
			return labelVO;
		}
		Label label = mapper.selectById(id);
		if (!ObjectUtils.isEmpty(label)) {
			labelVO = createLabelVO(label);
			redis.opsForValue().set(VO + id, labelVO, DURATION);
		}
		return labelVO;
	}
	
	public LabelVO createLabelVO(Label label) {
		LabelVO labelVO = LabelTransform.entity2VO(label);
		Classify classify = classifyService.selectById(label.getClassifyId());
		if (null != classify) {
			labelVO.setClassifyName(classify.getName());
		}
		return labelVO;
	}
	
	public List<LabelVO> createListVO(List<Label> list) {
		List<LabelVO> voList = new ArrayList<>();
		for (Label label : list) {
			voList.add(createLabelVO(label));
		}
		return voList;
	}
	
	@Async ("Task")
	public void set(List<LabelVO> value, String key) {
		redis.opsForList().rightPushAll(key, value);
		redis.opsForList().getOperations().expire(key, DURATION);
	}
	
	@Async ("Task")
	public void del() {
		Set<String> keys = redis.keys(VO + "*");
		redis.delete(keys);
	}
}
